package com.smag.system.service.impl;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.smag.common.core.domain.AjaxResult;
import com.smag.system.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * User: NoahZor
 * Date: 2024/4/19
 */
@Service
@Slf4j
public class OssServiceImpl implements OssService {
    private OSS ossClient;

    @Value("${spring.alioss.endpoint}")
    private String endpoint;

    @Value("${spring.alioss.access-key-id}")
    private String accessKeyId;

    @Value("${spring.alioss.access-key-secret}")
    private String accessKeySecret;

    @Value("${spring.alioss.bucket-name}")
    private String bucketName;

    private void getClient() {
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
    @Override
    public AjaxResult getUploadPolicy() {
        // 拼接出 host 地址
        String host = ("https://" + bucketName + "." + endpoint).intern();

        Map<String, String> respMap = null;
        try {
            getClient();
            // 设置过期时间
            // 秒数，这里设置 10s 就过期
            long expireTime = 60L;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000L;
            Date expiration = new Date(expireEndTime);

            // 指定请求的条件
            PolicyConditions policyConditions = new PolicyConditions();
            // 设置内容长度允许的字节数，最大是1048576000个字节，1MB=1048576个字节，这里限制最大是100MB
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 104857600);
            // 限制上传文件的前缀
            // 设置文件夹，这里按照日期分文件夹
            String dir = new SimpleDateFormat("yyyy/MM/dd").format(new Date()) + "/";
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            /// 生成policy
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("ossAccessKeyId", accessKeyId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
        } catch (OSSException oe) {
           log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            // 假设此方法存在 
           log.error("HTTP Status Code: {} ", oe.getRawResponseError());
           log.error("Error Message: {}", oe.getErrorMessage());
           log.error("Error Code: {}", oe.getErrorCode());
           log.error("Request ID: {}", oe.getRequestId());
           log.error("Host ID: {}", oe.getHostId());
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
           log.error("Error Message: {}", ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return AjaxResult.success("获取凭证成功", respMap);
    }

    @Override
    public void deleteFile(String filePath) {
        // 拼接出 host 地址
        String host = ("https://" + bucketName + "." + endpoint).intern();
        try {
            getClient();
            // 删除文件或目录。如果要删除目录，目录必须为空。
            if (filePath != null && !filePath.isEmpty()) {
                System.out.println("FIle" + filePath);
                int index = filePath.indexOf(host);
                if (index >= 0) {
                    ossClient.deleteObject(bucketName, filePath.substring(host.length() + 1));
                }
            }
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message: {}", oe.getErrorMessage());
            log.error("Error Code: {}", oe.getErrorCode());
            log.error("Request ID: {}", oe.getRequestId());
            log.error("Host ID: {}", oe.getHostId());
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message: {}",ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
